package com.joven.shelltest.controller;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonView;
import com.joven.shelltest.annotation.AutoIdempotent;
import com.joven.shelltest.annotation.ParamLog;
import com.joven.shelltest.dto.*;
import com.joven.shelltest.entity.SysUserModel;
import com.joven.shelltest.model.Mail;
import com.joven.shelltest.service.JovenService;
import com.joven.shelltest.service.StrategyMapFactory;
import com.joven.shelltest.service.SysUserService;
import com.joven.shelltest.service.TokenService;
import com.joven.shelltest.utils.RedisLockUtils;
import com.joven.shelltest.utils.chain.ProductService;
import com.joven.shelltest.utils.jsonview.JsonViewDto;
import com.joven.shelltest.utils.jsonview.UserView;
import com.joven.shelltest.utils.obersever.SubjectFactory;
import com.joven.shelltest.utils.ruleExcute.RuleDto;
import com.joven.shelltest.utils.ruleExcute.RuleFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * @Author wzj
 * @Date 2023-04-25 20:15
 **/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/jojo")
public class JovenController {

    private final TokenService tokenService;

    @GetMapping("/hello")
    public String testShell(String path) {
        log.info(path);
        log.info("idCard:{}", path);
        log.info("身份证:{}", path);
        System.out.println(Thread.currentThread().getName());
        return "Hello path <> " + path;
    }

    @GetMapping("/outLog")
    public String outLog(String data) throws InterruptedException {
        log.info("startTime:{}", LocalDateTime.now());
        log.info("getData:{}", data);
        Thread.sleep(1000L);
        log.info("endTime:{}", LocalDateTime.now());
        String threadName = Thread.currentThread().getName();
        System.out.println(Thread.currentThread().getName());
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        return getLogValue(threadName, this.getClass().getSimpleName(), methodName);
    }

    private String getLogValue(String threadName, String packageName, String methodName) {
        StringBuilder stringBuilder = new StringBuilder();
        FileInputStream fileInputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader bufferedReader = null;
        try {
            //创建文件
            File file = new File("D:\\spring-boot-single\\logs\\system.log");
            //获取文件输入流
            fileInputStream = new FileInputStream(file);
            //使用utf-8读流
            inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
            bufferedReader = new BufferedReader(inputStreamReader);
            //读行
            String lineString = bufferedReader.readLine();
            //判断，是否数据
            while (lineString != null) {
                // ‘\r’是为了在前端展示时换行
                if (lineString.contains(threadName) && lineString.contains(packageName) && lineString.contains(methodName)) {
                    stringBuilder.append(lineString).append("\r");
                }
                lineString = bufferedReader.readLine();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStreamReader != null) {
                try {
                    inputStreamReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return stringBuilder.toString();
    }

    @GetMapping("/helloSensitive")
    public TestUserInfoDto helloSensitive() {
        TestUserInfoDto userInfoDto = new TestUserInfoDto();
        userInfoDto.setName("王珂珂");
        userInfoDto.setIdCard("330821199511260031");
        userInfoDto.setPhone("18757809311");
        userInfoDto.setAddress("衢州市柯城区白云街道衢时代10楼");
        userInfoDto.setPassword("Xasz@123");
        return userInfoDto;
    }

    @GetMapping("/sensitiveSimple")
    public EmployeeDto sensitiveSimple() {
        EmployeeDto userInfoDto = new EmployeeDto();
        userInfoDto.setName("王珂珂");
        userInfoDto.setSalary(125.25);
        userInfoDto.setDepartment("公关");
        userInfoDto.setIdCard("330821199511260031");
        return userInfoDto;
    }

    /**
     * 请求带@AutoIdempotent注解 需在请求headers内加TOKEN_NAME定义的属性 并填入#getToken()获取到的值
     *
     * @return /
     */
    @PostMapping("/get/token")
    public String getToken() {
        String token = tokenService.createToken();
        if (StringUtils.isNotEmpty(token)) {
            ResultDto resultVo = new ResultDto();
            resultVo.setStatusCode(HttpStatus.OK.value());
            resultVo.setMessage(HttpStatus.OK.getReasonPhrase());
            resultVo.setData(token);
            return JSONUtil.toJsonStr(resultVo);
        }
        return StringUtils.EMPTY;
    }

    /**
     * 注解@AutoIdempotent 每expireTime可以请求一次
     *
     * @return /
     */
    @AutoIdempotent(expire = 30L)
    @PostMapping("/test/Idempotence")
    public String testIdempotence() {
        return HttpStatus.OK.getReasonPhrase();
    }

    @ParamLog(module = "ParamLog", regex = "#{resultDto.statusCode}")
    @PostMapping("/testParamLog")
    public String testParamLog(@RequestBody ResultDto resultDto) {
        return resultDto.getMessage();
    }

    @ParamLog(module = "ParamLog", regex = "#{name}")
    @GetMapping("/testParamLog1")
    public String testParamLog1(String name) {
        return name;
    }

    private final RedisLockUtils redisLockUtils;

    @GetMapping("/getRedisLock")
    public boolean getRedisLock() {
        return redisLockUtils.getLock("jovenLock", "251126");
    }

    private final JovenService jovenService;

    /**
     * 异步监听处理
     *
     * @param mail 监听类
     */
    @PostMapping("/sendMail")
    public void sendMail(@RequestBody Mail mail) {
        jovenService.sendMail(mail);
    }

    private final ProductService productService;

    /**
     * 责任链模式
     */
    @GetMapping("/contextLoad")
    public void contextLoads() {
        ProductVO param = ProductVO.builder()
                .skuId(123L)
                .skuName("测试商品")
                .imgPath("https://www.baidu.com")
                .price(new BigDecimal(1))
                .stock(1)
                .build();
        productService.createProduct(param);
    }

    private final StrategyMapFactory strategyMapFactory;

    @GetMapping("/grantType")
    public String grantType(String type, String dealId) {
        return strategyMapFactory.getResult(type, dealId);
    }

    private final SubjectFactory subjectFactory;

    @GetMapping("/observer")
    public void observerTest(String temperature, String pressure, String humidity) {
        subjectFactory.processing(Float.parseFloat(temperature), Float.parseFloat(pressure), Float.parseFloat(humidity));
    }

    private final SysUserService sysUserService;

    @GetMapping("/testLocalDB")
    public List<SysUserModel> testLocalDB(Integer status) {
        List<SysUserModel> userModelList = sysUserService.getUsrByStatus(status);
        System.out.println(userModelList.size());
        return userModelList;
    }

    @PostMapping("/testLocalInsert")
    public void testLocalInsert(@RequestBody SysUserModel sysUserModel) {
        sysUserService.insertIntoValuesAndMapping(sysUserModel);
    }

    @GetMapping("/testLocalQuery")
    public List<SysUserModel> testLocalQuery(String idCard) {
        return sysUserService.getUsrDim(idCard);
    }

    private final RuleFactory ruleFactory;

    @GetMapping("/testRule")
    public String testRule(int ruleType, String ruleName1, String ruleName2) {
        RuleDto dto = new RuleDto();
        dto.setHeight(170);
        dto.setAge(11);
        dto.setAddress("北京市东三环");
        boolean ruleResult = ruleFactory.execute(ruleType, dto, Arrays.asList(ruleName1, ruleName2));
        if (ruleResult) {
            return "无须买票";
        } else {
            return "请买票";
        }
    }

    @PostMapping("/testValid")
    public String testValid(@Validated @RequestBody ValidTestDto param){
        return param.getPrice().toString();
    }

    @GetMapping("/testJsonView")
    @JsonView(UserView.Full.class)
    public JsonViewDto testJsonView(){
        JsonViewDto viewDto = new JsonViewDto();
        viewDto.setName("王珂珂");
        viewDto.setAge("23");
        viewDto.setSex("女");
        viewDto.setAddress("河南周口");
        viewDto.setIdCard("330821199511260031");
        viewDto.setPhone("18757809312");
        viewDto.setPassword("Xasz@123");
        viewDto.setAccount("JS6215613215134");
        return viewDto;
    }

    @GetMapping("/jsonView/map")
    public MappingJacksonValue jacksonValueMap() {
        JsonViewDto viewDto = new JsonViewDto();
        viewDto.setName("胡瑞");
        viewDto.setAge("24");
        viewDto.setSex("女");
        viewDto.setAddress("河南驻马店");
        viewDto.setIdCard("330821199511260032");
        viewDto.setPhone("18757809311");
        viewDto.setPassword("Xasz@1234");
        viewDto.setAccount("ZS6215613215132");
        MappingJacksonValue value = new MappingJacksonValue(viewDto);
        value.setSerializationView(UserView.WithoutPassword.class);
        return value  ;
    }

    @Value("${spring.datasource.password}")
    private String password ;

    @GetMapping("/test/jasypt/decrypt")
    public String jasyptDecrypt() {
        return password;
    }
}
